package com.oracle.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oracle.application.entity.Orderitems;
import com.oracle.application.entity.Orders;
import com.oracle.application.entity.vo.*;
import com.oracle.application.mapper.OrderitemsMapper;
import com.oracle.application.mapper.OrdersMapper;
import com.oracle.application.service.IOrdersService;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisCluster;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 莉丝妲黛
 * @since 2021-06-24
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersService {
    /**
     * Redis
     */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private OrderitemsMapper orderitemsMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    public DirectExchange orderCreateExchange;
    /**
     * 创建一个订单中确认的令牌值(ToKen)
     * 创建地址信息
     * 根据所选购物车信息创建订单详细内容
     * 计算参考总价
     *
     * @return
     */
    @Override
    public OrderConfirmVo createOrderConfirm() {
        //创建订单令牌
        String orderToKenValue = UUID.randomUUID().toString().replaceAll("-", "");

        AddressVo addressVo = new AddressVo();
        addressVo.setArea("北京");
        addressVo.setAddress("北京市丰台区");
        addressVo.setPhone("15565635449");
        addressVo.setConsignee("李四");
        addressVo.setIsDefault(false);

        AddressVo addressVo2 = new AddressVo();
        addressVo2.setArea("北京");
        addressVo2.setAddress("北京市丰台区");
        addressVo2.setPhone("15565635449");
        addressVo2.setConsignee("李五");
        addressVo2.setIsDefault(true);

        AddressVo addressVo3 = new AddressVo();
        addressVo3.setArea("北京");
        addressVo3.setAddress("北京市丰台区");
        addressVo3.setPhone("15565635449");
        addressVo3.setConsignee("李六");
        addressVo3.setIsDefault(false);

        List<AddressVo> addressVoList = new ArrayList<>();
        addressVoList.add(addressVo);
        addressVoList.add(addressVo2);
        addressVoList.add(addressVo3);

        //创建订单明细显示信息
        OrderitemsVo orderitemsVo = new OrderitemsVo();
        orderitemsVo.setSkname("大拖鞋");
        orderitemsVo.setImage("https://springboot-1306105688.cos.ap-beijing.myqcloud.com/test/image/dd28c708-e1a2-4782-b412-e2a42363a553.png");
        orderitemsVo.setNum(1);
        orderitemsVo.setSkusn("202106251");
        orderitemsVo.setPrice(new BigDecimal(150.00));

        OrderitemsVo orderitemsVo2 = new OrderitemsVo();
        orderitemsVo2.setSkname("大西瓜");
        orderitemsVo2.setImage("https://springboot-1306105688.cos.ap-beijing.myqcloud.com/test/image/dd28c708-e1a2-4782-b412-e2a42363a553.png");
        orderitemsVo2.setNum(1);
        orderitemsVo2.setSkusn("202106251");
        orderitemsVo2.setPrice(new BigDecimal(200.00));

        OrderitemsVo orderitemsVo3 = new OrderitemsVo();
        orderitemsVo3.setSkname("大飞机");
        orderitemsVo3.setImage("https://springboot-1306105688.cos.ap-beijing.myqcloud.com/test/image/dd28c708-e1a2-4782-b412-e2a42363a553.png");
        orderitemsVo3.setNum(1);
        orderitemsVo3.setSkusn("202106251");
        orderitemsVo3.setPrice(new BigDecimal(300.00));

        List<OrderitemsVo> orderitemsVoList = new ArrayList<>();
        orderitemsVoList.add(orderitemsVo);
        orderitemsVoList.add(orderitemsVo2);
        orderitemsVoList.add(orderitemsVo3);

        BigDecimal totalPrice = new BigDecimal("0.0");
        for (OrderitemsVo vo : orderitemsVoList) {
            //multiply 乘
            totalPrice = totalPrice.add(vo.getPrice().multiply(new BigDecimal(vo.getNum())));
        }
        System.out.println("总价为:");
        System.out.println(totalPrice);

        //订单令牌存入redis
        final String orderTokenKey = "pay:ordertoken:" + 1;
        this.redisTemplate.boundValueOps(orderTokenKey).set(orderToKenValue);
        String payMethod = "支付宝-在线支付";
        OrderConfirmVo orderConfirmVo = new OrderConfirmVo();
        orderConfirmVo.setOrderToKen(orderToKenValue);
        orderConfirmVo.setOrderitemsVoList(orderitemsVoList);
        orderConfirmVo.setAddressVoList(addressVoList);
        orderConfirmVo.setPayMethod(payMethod);
        orderConfirmVo.setTotalPrice(totalPrice.setScale(2, BigDecimal.ROUND_DOWN));

        return orderConfirmVo;
    }


    @Override
    public Map<String, Object> submitOrder(OrderSubmitVo orderSubmitVo) {
        Map<String, Object> map =new HashMap<>();
        //创建订单后需要为购买的的商品分配库存
        //如果下单后的一定时间内用户分配库存 不能一直占用 需要确认订单状态 当订单完成支付了  任务订单被确认 是有效订单
        //订单没有支付或者支付都要对订单的状态进行变更；
        //当用户下单后 订单创建成功时   将订单信息丢进mq 这个队列没有消费着
        //队列有效时间为系统支付范围之间 30分
        //监控死信队列  获取订单消息 拿到订单消息 根据订单id  或者编号查询数据库 询问是否支付
        //进行校验(token)令牌值
        final String orderTokenKey = "pay:ordertoken:" + 1;
        //根据key获取订单中的token -> 判断 -> 删除
        String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        //lua脚本方式释放锁
        Long result = this.redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                Object nativeConnection = connection.getNativeConnection();

                // 集群模式
                if (nativeConnection instanceof JedisCluster) {
                    return (Long) ((JedisCluster) nativeConnection).eval(script, Arrays.asList(orderTokenKey), Arrays.asList(orderSubmitVo.getOrderToKen()));
                }
                return null;
            }
        });
        //判断令牌是否存在
        if (result == null || result == 0) {
            map.put("code", 500);
            return map;
        }
        //验证库存是否充足
        //根据购物车内的商品id  去调用库存服务 仓库位置  地址  仓库中有商品 数量 那个仓库  ----
        //那个最近的仓库有货
        //id 商品id xxxx   num---;
        //创建订单并创建明细
        //Mq2个队列(当消息在有效时间  系统系统待支付的一个是时间范围)
        //消息在时间内没有被消费 该条消息将进入死信队列
        //在死信队列 获取消息进行订单的变更 如果订单在数据库中没有更新为已经支付状态时  将对订单状态变更为关闭
        try {
            Orders orders = new Orders();
            orders.setTotalprice(new BigDecimal("0"));
            //通过用户选择的收货地址中的信息来提取电话
            orders.setPhone(orderSubmitVo.getAddressVo().getPhone());
            orders.setAddress(orderSubmitVo.getAddressVo().getAddress());
            orders.setArea(orderSubmitVo.getAddressVo().getArea());
            orders.setZipcode("459000");
            orders.setMember(1);
            orders.setConsigenn(orderSubmitVo.getAddressVo().getConsignee());
            orders.setOrderstatus(0);
            orders.setPaystatus(0);
            //此订单的支付方式
            orders.setPaymethod(orderSubmitVo.getPayMethod());
            orders.setCreatedate(LocalDateTime.now());
            orders.setModifydate(LocalDateTime.now());
            //设置订单超时的时间
            orders.setExpirtdate(orders.getCreatedate().plusMinutes(30));

            //购物车信息(skux信息 名称 价格 购物车中加入的数量) 变为订单明细信息
            List<Orderitems> orderItems=orderSubmitVo.getOrderitemsVoList().stream().map(orderitemsVo -> {
                Orderitems orderitems =new Orderitems();
                BeanUtils.copyProperties(orderitemsVo, orderitems);
                return  orderitems;
            }).collect(Collectors.toList());
            //计算总价
            BigDecimal totalPrice =new BigDecimal("0.0");
            for (Orderitems orderItem : orderItems) {
                totalPrice=totalPrice.add(orderItem.getPrice().multiply(new BigDecimal(orderItem.getNum())));
            }
            orders.setTotalprice(totalPrice);
            //mybatis plus  中自带的随机值
            orders.setOrdersn(IdWorker.getTimeId());
            //保存订单
            this.ordersMapper.insert(orders);
            for (Orderitems orderItem : orderItems) {
                orderItem.setOrders(orders.getId());
                this.orderitemsMapper.insert(orderItem);
            }
            //orderItems.stream().forEach(orderitems ->orderitems.setOrders(orders.getId()));


            OrdersVo ordersVo=new OrdersVo();
            BeanUtils.copyProperties(orders,ordersVo);
            this.amqpTemplate.convertAndSend(this.orderCreateExchange.getName(),"order.create", JSONObject.toJSONString(ordersVo));
            map.put("date", ordersVo);
            //根据获取购物车服务 通过购物车勾选的选项来进行订单明细的创建
        } catch (Exception e) {
            throw e;
        }
        return map;
    }

    /**
     * 根据订单编号修改
     * @param OrderSn 根据订单唯一编号
     * @return 受影响的行数
     */
    @Override
    public int updateOrderStatus(String OrderSn) {
        return this.ordersMapper.updateOrderStatus(OrderSn);
    }
}

